package org.jsola.hr.service.impl;

import com.alipay.api.domain.UserVo;
import org.apache.commons.lang3.StringUtils;
import org.jsola.admin.entity.SiteDO;
import org.jsola.common.DateKit8;
import org.jsola.core.Page;
import org.jsola.exception.ParamException;
import org.jsola.hr.common.ExampleKit;
import org.jsola.hr.constant.HrConstants;
import org.jsola.hr.dao.IRegistrationRecordDAO;
import org.jsola.hr.dto.RegistrationRecordAddDTO;
import org.jsola.hr.dto.RegistrationRecordUpdateDTO;
import org.jsola.hr.entity.*;
import org.jsola.hr.provider.IAdminProviderService;
import org.jsola.hr.provider.IPermissionProviderService;
import org.jsola.hr.provider.IUserProviderService;
import org.jsola.hr.query.RegistrationRecordQuery;
import org.jsola.hr.service.*;
import org.jsola.hr.vo.*;
import org.jsola.permission.entity.RoleMemberDO;
import org.jsola.permission.query.RoleMemberQuery;
import org.jsola.permission.vo.RoleMemberListVO;
import org.jsola.user.core.TokenUser;
import org.jsola.user.vo.UserVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import tk.mybatis.mapper.entity.Example;

import java.util.*;
import java.util.stream.Collectors;

import static org.jsola.hr.constant.HrPermissionConstants.COMPANY_SUBJECT_TYPE;

/**
 * 登录记录
 *
 * @author zhr
 */
@Service("hrRegistrationRecordServiceImpl")
public class RegistrationRecordServiceImpl implements IRegistrationRecordService {

    @Autowired
    private IRegistrationRecordDAO registrationRecordDAO;
    @Autowired
    private ICompanyService companyService;
    @Autowired
    private IChildCompanyService childCompanyService;
    @Autowired
    private IChannelService channelService;
    @Autowired
    private IHrPermissionService hrPermissionService;
    @Autowired
    private IAdminProviderService adminProviderService;

    @Autowired
    private IPermissionProviderService permissionProviderService;

    @Autowired
    private IUserProviderService userProviderService;

    @Autowired
    private IGroupCompanyService groupCompanyService;

    @Autowired
    private IChannelCompanyService channelCompanyService;

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public RegistrationRecordVO save(RegistrationRecordAddDTO registrationRecordAddDTO, TokenUser tokenUser) {
        // 转DO
        RegistrationRecordDO registrationRecordDO = registrationRecordAddDTO.to(RegistrationRecordDO.class);
        // 保存
        registrationRecordDO = save(registrationRecordDO, tokenUser.getSiteId(), tokenUser.getUserId());
        return registrationRecordDO.to(RegistrationRecordVO.class);
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public int update(RegistrationRecordUpdateDTO registrationRecordUpdateDTO, TokenUser tokenUser) {
        //转DO
        RegistrationRecordDO registrationRecordDO = registrationRecordUpdateDTO.to(RegistrationRecordDO.class);
        //根据主键更新，只更新非null值
        return updateByIdSelective(registrationRecordDO, tokenUser.getSiteId(), tokenUser.getUserId());
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public int deleteByIds(TokenUser tokenUser, String... registrationRecordIds) {
        return logicalDeleteByIds(tokenUser.getSiteId(), tokenUser.getUserId(), (Object[]) registrationRecordIds);
    }


    @Override
    public RegistrationRecordVO selectById(String registrationRecordId, String siteId) {
        RegistrationRecordDO registrationRecordDO = selectDOById(registrationRecordId, siteId);
        if (registrationRecordDO == null) {
            return null;
        }
        return registrationRecordDO.to(RegistrationRecordVO.class);
    }

    @Override
    public List<RegistrationRecordListVO> select(RegistrationRecordQuery registrationRecordQuery, String siteId) {
        List<RegistrationRecordDO> registrationRecordDOList = selectDO(registrationRecordQuery, siteId);
        if (CollectionUtils.isEmpty(registrationRecordDOList)) {
            return registrationRecordDOList == null ? null : new ArrayList<>();
        }
        return registrationRecordDOList.stream()
                .map(registrationRecordDO -> registrationRecordDO.to(RegistrationRecordListVO.class))
                .collect(Collectors.toList());
    }

    @Override
    public int selectCount(RegistrationRecordQuery registrationRecordQuery, String siteId) {
        Example example = buildExample(registrationRecordQuery, siteId);
        return registrationRecordDAO.selectCountByExample(example);
    }

    @Override
    public Page<RegistrationRecordListVO> selectPage(RegistrationRecordQuery registrationRecordQuery, String siteId) {
        Example example = buildExample(registrationRecordQuery, siteId);
        Page<RegistrationRecordDO> page = registrationRecordDAO.selectPageByExample(example,
                registrationRecordQuery.getPageNo(),
                registrationRecordQuery.getPageSize());

        return page.to(RegistrationRecordListVO.class);
    }

    @Override
    public RegistrationRecordDO selectDOById(String registrationRecordId, String siteId) {
        return listById(registrationRecordId, siteId);
    }

    @Override
    public List<RegistrationRecordDO> selectDO(RegistrationRecordQuery registrationRecordQuery, String siteId) {
        Example example = buildExample(registrationRecordQuery, siteId);
        return registrationRecordDAO.selectByExample(example);
    }

    @Override
    public RegistrationRecordVO selectByUserId(TokenUser tokenUser) {
        RegistrationRecordVO registrationRecordVO = null;

        //判断有历史登录的用工单位，现在是否有权限
        UserCompanyVO userCompanyVO = childCompanyService.selectByUserId(tokenUser.getUserId(), tokenUser.getSiteId());

        //有权限的用工单位
        List<String> subjectIds = new ArrayList<>();
        Example example = new Example(RegistrationRecordDO.class);
        if (userCompanyVO.getIsAllChildCompany()) {
            //有全部用工单位权限
            example.and()
                    .andEqualTo("valid", true)
                    .andEqualTo("createUserId", tokenUser.getUserId());
            example.orderBy("gmtCreate").desc();
            List<RegistrationRecordDO> registrationRecordDOList = registrationRecordDAO.selectByExample(example);
            registrationRecordVO = getRegistrationRecordVO(registrationRecordDOList, tokenUser);


            List<CompanyDO> companyList = companyService.selectAll(tokenUser.getSiteId());
            subjectIds = companyList.stream().map(CompanyDO::getId).collect(Collectors.toList());

        } else {
            //有部分用工单位权限

            List<String> companyIds = userCompanyVO.getCompanyIds();
            if (!CollectionUtils.isEmpty(companyIds)) {
                subjectIds.addAll(companyIds);
            }

            List<String> groupIds = userCompanyVO.getGroupIds();
            if (!CollectionUtils.isEmpty(groupIds)) {
                List<String> companyIdsByGroup = groupCompanyService.selectCompanyIdListByGroupIds(groupIds, tokenUser.getSiteId());
                subjectIds.addAll(companyIdsByGroup);
            }

            if (!CollectionUtils.isEmpty(subjectIds)) {
                example.and()
                        .andEqualTo("valid", true)
                        .andEqualTo("createUserId", tokenUser.getUserId())
                        .andIn("subjectId", subjectIds)
                ;
                List<RegistrationRecordDO> registrationRecordDOList = registrationRecordDAO.selectByExample(example);
                registrationRecordVO = getRegistrationRecordVO(registrationRecordDOList, tokenUser);
            } else {
                //管理员没有负责的用工单位，查询是不是一个渠道
                //查询渠道负责的用工单位集合
                ChannelDO channelDO = channelService.selectByUserIdAndSite(tokenUser.getUserId(), tokenUser.getSiteId());
                if (channelDO != null) {
                    List<ChannelCompanyVO> channelCompanyDOList = channelCompanyService.selectByChannelId(channelDO.getId(), tokenUser.getSiteId());
                    Boolean isAll = false;
                    for (ChannelCompanyVO channelCompanyVO : channelCompanyDOList) {
                        isAll = channelCompanyVO.getIsAllChildCompany();
                        if (isAll){
                            List<CompanyDO> companyList = companyService.selectAll(tokenUser.getSiteId());
                            subjectIds = companyList.stream().map(CompanyDO::getId).collect(Collectors.toList());
                            break;
                        } else {
                            subjectIds.add(channelCompanyVO.getEmployerId());
                        }
                    }
                    if (isAll) {
                        example.and()
                                .andEqualTo("valid", true)
                                .andEqualTo("createUserId", tokenUser.getUserId())
                        ;
                        List<RegistrationRecordDO> registrationRecordDOList = registrationRecordDAO.selectByExample(example);
                        registrationRecordVO = getRegistrationRecordVO(registrationRecordDOList, tokenUser);
                    } else {
                        if (CollectionUtils.isEmpty(subjectIds)) {
                            throw new ParamException("暂无用工单位权限");
                        }
                        example.and()
                                .andEqualTo("valid", true)
                                .andEqualTo("createUserId", tokenUser.getUserId())
                                .andIn("subjectId", subjectIds)
                        ;
                        List<RegistrationRecordDO> registrationRecordDOList = registrationRecordDAO.selectByExample(example);
                        registrationRecordVO = getRegistrationRecordVO(registrationRecordDOList, tokenUser);
                    }
                }
            }
        }

        if (CollectionUtils.isEmpty(subjectIds)) {
            throw new ParamException("暂无用工单位权限");
        }

        if (registrationRecordVO != null) {
            //登录手机号
            UserVO userVO = userProviderService.selectById(tokenUser.getUserId());
            if (userVO != null) {
                registrationRecordVO.setPhone(userVO.getPhone());
            }
            return registrationRecordVO;
        }
        // 未产生登录记录
        //渠道信息
        List<HrSiteVO> hrSiteVOList = channelService.selectSiteByUserId(tokenUser.getUserId());
        ParamException.notEmpty(hrSiteVOList, "用户没有权限");
        for (HrSiteVO hrSiteVO : hrSiteVOList) {
            String siteId = hrSiteVO.getId();
            Map<String, SiteDO> siteIdDoMap = adminProviderService.selectSiteMap();
            SiteDO siteDO = siteIdDoMap.get(siteId);
            if (siteDO == null) {
                continue;
            }
            registrationRecordVO = new RegistrationRecordVO();
            // 是否为管理员
            getAdminName(registrationRecordVO, siteId, tokenUser);
            // 渠道Id
            ChannelDO channelDO = channelService.selectByUserIdAndSite(tokenUser.getUserId(), tokenUser.getSiteId());
            if (channelDO != null) {
                registrationRecordVO.setChannelId(channelDO.getId());
            }
            //返回的名称默认是某个用工单位，不能直接是租户，应该返回某个用工单位，就随机找有个有权限的用工单位
            String firstCompanyId = subjectIds.get(0);
            Map map = companyService.searchCompanyName(firstCompanyId, tokenUser);
            String name = (String) map.get("name");
            String subjectId = (String) map.get("subjectId");
            String subjectType = (String) map.get("subjectType");
            String parentSubjectId = (String) map.get("parentSubjectId");
            String parentSubjectType = (String) map.get("parentSubjectType");


            registrationRecordVO.setCompanyName(name);
            registrationRecordVO.setSubjectId(subjectId);
            registrationRecordVO.setSubjectType(subjectType);
            registrationRecordVO.setParentSubjectId(parentSubjectId);
            registrationRecordVO.setParentSubjectType(parentSubjectType);
            registrationRecordVO.setEmployeeName(tokenUser.getUserName());
            //登录手机号
            UserVO userVO = userProviderService.selectById(tokenUser.getUserId());
            if (userVO != null) {
                registrationRecordVO.setPhone(userVO.getPhone());
            }

            return registrationRecordVO;
        }
        throw new ParamException("登录权限已被取消");
    }


    /**
     * 用户登录记录中 获取符合条件的最新一条
     *
     * @param registrationRecordDOList 登录记录
     * @param tokenUser                登录用户
     * @return 最新一条
     */
    private RegistrationRecordVO getRegistrationRecordVO(List<RegistrationRecordDO> registrationRecordDOList, TokenUser tokenUser) {
        Map<String, SiteDO> siteIdDoMap = adminProviderService.selectSiteMap();
        for (RegistrationRecordDO registrationRecordDO : registrationRecordDOList) {
            String id;
            String name;
            // 站点信息 肯定有
            SiteDO siteDO = siteIdDoMap.get(registrationRecordDO.getSiteId());

            // 当天开始时间
            Date dayStart = DateKit8.getStartTime(new Date());
            if (siteDO == null || (siteDO.getExpireDate() != null && siteDO.getExpireDate().getTime() < dayStart.getTime())) {
                continue;
            }
            if ("company".equals(registrationRecordDO.getSubjectType())) {
                // 公司的上级 可能是分组 也可能是站点
                CompanyDO companyDO = companyService.selectDOByIdNotSite(registrationRecordDO.getSubjectId());
                if (companyDO == null) {
                    continue;
                }
                if ("site".equals(registrationRecordDO.getParentSubjectType())) {
                    // 上级是站点
                    name = siteDO.getName() + "," + companyDO.getName();
                    id = siteDO.getId() + "," + companyDO.getId();
                } else if ("group".equals(registrationRecordDO.getParentSubjectType())) {
                    // 上级是分组
                    ChildCompanyDO childCompanyDO = childCompanyService.selectDOByIdNotSite(registrationRecordDO.getParentSubjectId());
                    if (childCompanyDO == null) {
                        continue;
                    }
                    name = siteDO.getName() + "," + childCompanyDO.getName() + "," + companyDO.getName();
                    id = siteDO.getId() + "," + childCompanyDO.getId() + "," + companyDO.getId();
                } else {
                    continue;
                }

            } else if ("group".equals(registrationRecordDO.getSubjectType())) {
                // 分组的上级一定是租户
                ChildCompanyDO childCompanyDO = childCompanyService.selectDOByIdNotSite(registrationRecordDO.getSubjectId());
                if (childCompanyDO == null) {
                    continue;
                }
                name = siteDO.getName() + "," + childCompanyDO.getName();
                id = siteDO.getId() + "," + childCompanyDO.getId();
            } else if ("site".equals(registrationRecordDO.getSubjectType())) {
                // 登录信息为站点 直接返回站点信息
                name = siteDO.getName();
                id = siteDO.getId();
            } else {
                continue;
            }
            RegistrationRecordVO registrationRecordVO = registrationRecordDO.to(RegistrationRecordVO.class);
            // 是否为管理员 非渠道人员 就是管理员
            getAdminName(registrationRecordVO, registrationRecordDO.getSiteId(), tokenUser);
            // 渠道Id
            ChannelDO channelDO = channelService.selectByUserIdAndSite(tokenUser.getUserId(), registrationRecordDO.getSiteId());
            if (channelDO != null) {
                registrationRecordVO.setChannelId(channelDO.getId());
            }
            registrationRecordVO.setCompanyName(name);
            registrationRecordVO.setEmployeeName(tokenUser.getUserName());
            registrationRecordVO.setSubjectId(id);
            return registrationRecordVO;
        }
        return null;
    }

    /**
     * 添加管理员名称
     *
     * @param registrationRecordVO 登录记录对象（放入是否管理员 和 角色名称）
     * @param siteId               对应站点Id
     * @param tokenUser            登录用户
     */
    private void getAdminName(RegistrationRecordVO registrationRecordVO, String siteId, TokenUser tokenUser) {
        // 管理员
        List<RoleMemberDO> roleMemberDOList = permissionProviderService
                .selectHrRoleMemberByUserIdAndSiteId(tokenUser.getUserId(), siteId);
        if (CollectionUtils.isEmpty(roleMemberDOList)) {
            // 非管理员
            registrationRecordVO.setIsAdmin(false);
            registrationRecordVO.setAdminName("渠道员");
        } else {
            registrationRecordVO.setIsAdmin(true);
            // 系统管理员
            boolean anyMatch = roleMemberDOList.parallelStream().anyMatch(roleMemberDO
                    -> "system".equals(roleMemberDO.getSubjectType()));
            if (anyMatch) {
                registrationRecordVO.setAdminName("超级管理员");
            } else {
                // hr角色
                RoleMemberDO roleMemberDO = roleMemberDOList.get(0);
                // 管理员
                registrationRecordVO.setAdminName(roleMemberDO.getRoleName());
            }
        }
    }

    /**
     * 根据查询参数，构建example
     *
     * @param registrationRecordQuery 查询参数
     * @param siteId                  所属站点id
     * @return example
     */
    private Example buildExample(RegistrationRecordQuery registrationRecordQuery, String siteId) {
        Example example = new Example(RegistrationRecordDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("siteId", siteId);
        // 排序
        ExampleKit.setExampleOrder(example, registrationRecordQuery.getOrders());
        return example;
    }
}




